#include "DocumentObjectInspector.h"

#include "Document.h"
#include "DocumentObjectTreeModel.h"
#include "IDocumentObject.h"
#include "ObjectPropertyBrowser.h"

#include <QDebug>
#include <QItemSelection>
#include <QMetaObject>
#include <QMetaProperty>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QSplitter>
#include <QTreeView>
#include <QVBoxLayout>

using namespace LDO;

DocumentObjectInspector::DocumentObjectInspector(QWidget *parent):
    QWidget(parent)
{
    m_model = new DocumentObjectTreeModel(this);
    m_view = new QTreeView();
    m_view->setModel(m_model);
    m_browser = new ObjectPropertyBrowser();

    auto splitter = new QSplitter(Qt::Vertical);
    splitter->addWidget(m_view);
    splitter->addWidget(m_browser);
    setLayout(new QVBoxLayout);
    layout()->addWidget(splitter);
    layout()->setMargin(0);
    layout()->setSpacing(0);
}

DocumentObjectInspector::~DocumentObjectInspector()
{
}

void DocumentObjectInspector::setDocumentObject(Document *document, IDocumentObject *object)
{
    if (m_document != nullptr)
    {
        m_document->disconnect(this);
    }

    m_browser->setObject(nullptr);
    m_document = document;
    m_model->setRootObject(document, object);

    if (m_document != nullptr)
    {
        applyDocumentSelection(m_document->selectedObjects(), QList<IDocumentObject *>());
        connect(document, &Document::selectedObjectsChanged,
                this, &DocumentObjectInspector::applyDocumentSelection);
        connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged,
                this, &DocumentObjectInspector::applyViewSelection);
    }
}

const IDocumentObject *DocumentObjectInspector::documentObject() const
{
    return m_model->rootObject();
}

void DocumentObjectInspector::applyDocumentSelection(const QList<IDocumentObject *> &current,
                                                     const QList<IDocumentObject *> &previous)
{
    Q_UNUSED(previous);
    QItemSelection itemSelection;
    for (auto object: current)
        itemSelection.append(QItemSelectionRange(m_model->index(object)));
    m_view->selectionModel()->select(itemSelection, QItemSelectionModel::ClearAndSelect);
    if (!itemSelection.isEmpty())
        m_view->scrollTo(itemSelection.at(0).topLeft());
}

void DocumentObjectInspector::applyViewSelection(const QItemSelection &selected, const QItemSelection &deselected)
{
    QSet<IDocumentObject*> selectedObjects = m_document->selectedObjects().toSet();
    for (const QItemSelectionRange selectionRange: deselected)
        for (const QModelIndex &index: selectionRange.indexes())
            selectedObjects.remove(m_model->documentObject(index));
    for (const QItemSelectionRange selectionRange: selected)
        for (const QModelIndex &index: selectionRange.indexes())
            selectedObjects.insert(m_model->documentObject(index));
    m_document->setSelectedObjects(selectedObjects.toList());
    if (!selectedObjects.isEmpty())
        m_browser->setObject(*selectedObjects.begin());
    else
        m_browser->setObject(nullptr);
}
